<template>
  <div class="relative inline-flex">
    <button ref="trigger" class="inline-flex items-center justify-center group" aria-haspopup="true"
      @click.prevent="dropdownOpen = !dropdownOpen" :aria-expanded="dropdownOpen">
      <img class="w-8 h-8 rounded-full" :src="UserAvatar" width="32" height="32" alt="User" />
      <div class="flex items-center truncate">
        <span
          class="ml-2 text-sm font-medium text-gray-600 truncate dark:text-gray-100 group-hover:text-gray-800 dark:group-hover:text-white">{{ displayName }}</span>
        <svg class="w-3 h-3 ml-1 text-gray-400 fill-current shrink-0 dark:text-gray-500" viewBox="0 0 12 12">
          <path d="M5.9 11.4L.5 6l1.4-1.4 4 4 4-4L11.3 6z" />
        </svg>
      </div>
    </button>
    <transition enter-active-class="transition duration-200 ease-out transform"
      enter-from-class="-translate-y-2 opacity-0" enter-to-class="translate-y-0 opacity-100"
      leave-active-class="transition duration-200 ease-out" leave-from-class="opacity-100" leave-to-class="opacity-0">
      <div v-show="dropdownOpen"
        class="origin-top-right z-10 absolute top-full min-w-44 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700/60 py-1.5 rounded-lg shadow-lg overflow-hidden mt-1"
        :class="align === 'right' ? 'right-0' : 'left-0'">
        <div class="pt-0.5 pb-2 px-3 mb-1 border-b border-gray-200 dark:border-gray-700/60">
          <div class="font-medium text-gray-800 dark:text-gray-100">{{ displayName }}</div>
          <div class="text-xs italic text-gray-500 dark:text-gray-400">{{ displayRole }}</div>
        </div>
        <ul ref="dropdown" @focusin="dropdownOpen = true" @focusout="dropdownOpen = false">
          <template v-if="loggedIn">
            <li>
              <router-link
                class="flex items-center px-3 py-1 text-sm font-medium text-violet-500 hover:text-violet-600 dark:hover:text-violet-400"
                to="/settings" @click="dropdownOpen = false">设置</router-link>
            </li>
            <li>
              <button
                class="flex w-full text-left items-center px-3 py-1 text-sm font-medium text-violet-500 hover:text-violet-600 dark:hover:text-violet-400"
                @click="onSignOut">Sign Out</button>
            </li>
          </template>
          <template v-else>
            <li>
              <router-link
                class="flex items-center px-3 py-1 text-sm font-medium text-violet-500 hover:text-violet-600 dark:hover:text-violet-400"
                to="/signin" @click="dropdownOpen = false">Sign In</router-link>
            </li>
          </template>
        </ul>
      </div>
    </transition>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import UserAvatar from '../images/user-avatar-32.png'
import { authApi, type UserResponse } from '../api/authService'

const props = defineProps({
  align: {
    type: String,
    default: 'right'
  }
})

const dropdownOpen = ref(false)
const trigger = ref<HTMLElement | null>(null)
const dropdown = ref<HTMLElement | null>(null)
const router = useRouter()

const profile = ref<UserResponse | null>(null)
const loggedIn = computed(() => !!localStorage.getItem('access_token'))
const displayName = computed(() => profile.value?.username || 'Guest')
const displayRole = computed(() => {
  const role = profile.value?.role
  if (!role) return 'Visitor'
  return role === 'admin' ? 'Administrator' : 'User'
})

const loadProfile = async () => {
  if (!loggedIn.value) {
    profile.value = null
    return
  }
  try {
    const me = await authApi.getCurrentUser()
    profile.value = me
  } catch {
    // token 失效
    profile.value = null
  }
}

const onSignOut = () => {
  dropdownOpen.value = false
  authApi.clearToken()
  profile.value = null
  router.push('/signin')
}

// close on click outside
const clickHandler = ({ target }: MouseEvent) => {
  if (!dropdownOpen.value || dropdown.value?.contains(target as Node) || trigger.value?.contains(target as Node)) return
  dropdownOpen.value = false
}

// close if the esc key is pressed
const keyHandler = ({ keyCode }: KeyboardEvent) => {
  if (!dropdownOpen.value || keyCode !== 27) return
  dropdownOpen.value = false
}

onMounted(() => {
  document.addEventListener('click', clickHandler)
  document.addEventListener('keydown', keyHandler)
  loadProfile()
})

onUnmounted(() => {
  document.removeEventListener('click', clickHandler)
  document.removeEventListener('keydown', keyHandler)
})
</script>
